package com.scorpio.agentuser.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.scorpio.agentuser.domain.AgentIncomeEntity;
import com.scorpio.agentuser.domain.AgentPayUserEntity;
import com.scorpio.agentuser.domain.AgentUserEntity;
import com.scorpio.agentuser.enums.QueryDataEnum;
import com.scorpio.agentuser.mapper.AgentIncomeMapper;
import com.scorpio.agentuser.service.AgentIncomeService;
import com.scorpio.agentuser.service.AgentPayUserService;
import com.scorpio.agentuser.service.AgentUserService;
import com.scorpio.common.annotation.DataSource;
import com.scorpio.common.enums.DataSourceType;
import com.scorpio.common.exception.CustomException;
import com.scorpio.common.service.impl.BaseServiceImpl;
import com.scorpio.common.utils.EchartsUtil;
import com.scorpio.common.utils.StringUtils;
import com.scorpio.redis.cachelock.RedisLock;
import com.scorpio.redis.constant.RedisConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@DataSource(DataSourceType.SLAVE)
public class AgentIncomeServiceImpl extends BaseServiceImpl<AgentIncomeMapper, AgentIncomeEntity> implements AgentIncomeService {

    @Autowired
    private AgentPayUserService agentPayUserService;

    @Autowired
    private AgentUserService agentUserService;

    @Autowired
    private RedisLock redisLock;

    @Override
    public JSONObject statistics(Long agentId, Integer type, Date quertDate) {
        JSONObject option = new JSONObject();
        JSONArray flag = new JSONArray();
        JSONArray direct = new JSONArray();
        JSONArray indirect = new JSONArray();
        JSONArray totali = new JSONArray();

        Calendar cal = Calendar.getInstance();
        if (type == 1) {
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);
            for (int i = 0; i < 23; i++) {
                flag.add((i + 1) + "时");
                cal.add(Calendar.HOUR_OF_DAY, 1);
                Float di = baseDao.countRegTotali(agentId, cal.getTime(), 1, QueryDataEnum.hour.getValue());
                Float in = baseDao.countRegTotali(agentId, cal.getTime(), 2, QueryDataEnum.hour.getValue());
                direct.add(di == null ? 0 : di);
                indirect.add(in == null ? 0 : in);
            }
        } else if (type == 2 || type == 3) {
            if (type == 3) {
                if (quertDate == null) {
                    throw new CustomException("无效查询");
                }
                cal.setTime(quertDate);
            }
            cal.add(Calendar.MONTH, 0);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            int day = cal.getActualMaximum(Calendar.DATE);
            for (int i = 0; i < day; i++) {
                flag.add((i + 1) + "日");
                cal.add(Calendar.DAY_OF_MONTH, 1);
                Float di = baseDao.countRegTotali(agentId, cal.getTime(), 1, QueryDataEnum.day.getValue());
                Float in = baseDao.countRegTotali(agentId, cal.getTime(), 2, QueryDataEnum.day.getValue());
                direct.add(di == null ? 0 : di);
                indirect.add(in == null ? 0 : in);
            }
        } else {
            throw new CustomException("无效查询");
        }
        for (int i = 0; i < direct.size(); i++) {
            int t = direct.getInteger(i) + indirect.getInteger(i);
            totali.add(t);

        }

        option.put("tooltip", EchartsUtil.tooltip());
        option.put("toolbox", EchartsUtil.toolbox("line", "line"));
        option.put("legend", EchartsUtil.legend("直推", "间推", "总计"));

        option.put("xAxis", EchartsUtil.xAxis("category", flag, "shadow"));
        JSONArray yAxis = new JSONArray();
        int min = EchartsUtil.toAverageMin(totali);
        int max = EchartsUtil.toAverageMax(totali);
        yAxis.add(EchartsUtil.yAxisItem("value", "直推", min, max, max / 10, "{value} 币"));
        yAxis.add(EchartsUtil.yAxisItem("value", "间推", min, max, max / 10, "{value} 币"));

        JSONArray series = new JSONArray();
        series.add(EchartsUtil.seriesItem("直推", "bar", direct, null));
        series.add(EchartsUtil.seriesItem("间推", "bar", indirect, null));
        series.add(EchartsUtil.seriesItem("总计", "line", totali, 1));
        option.put("yAxis", yAxis);
        option.put("series", series);
        return option;
    }

    @Override
    public JSONObject statisticsPie(Long agentId, Integer type, Date quertDate) {
        JSONObject json = new JSONObject();
        JSONObject direct = new JSONObject();
        JSONObject indirect = new JSONObject();
        Calendar cal = Calendar.getInstance();
        if (type == 1) {
            Float di = baseDao.countRegTotali(agentId, cal.getTime(), 1, QueryDataEnum.day.getValue());
            Float in = baseDao.countRegTotali(agentId, cal.getTime(), 2, QueryDataEnum.day.getValue());
            direct.put("value",di == null ? 0 : di);
            indirect.put("value",in == null ? 0 : in);
        } else if (type == 2 || type == 3) {
            if (type == 3) {
                if (quertDate == null) {
                    throw new CustomException("无效查询");
                }
                cal.setTime(quertDate);
            }

            Float di = baseDao.countRegTotali(agentId, cal.getTime(), 1, QueryDataEnum.month.getValue());
            Float in = baseDao.countRegTotali(agentId, cal.getTime(), 2, QueryDataEnum.month.getValue());
            direct.put("value",di == null ? 0 : di);
            indirect.put("value",in == null ? 0 : in);
        } else {
            throw new CustomException("无效查询");
        }
        direct.put("name", "直推收益");
        indirect.put("name", "间推收益");
        JSONArray data = new JSONArray();
        data.add(direct);
        data.add(indirect);
        JSONArray series = new JSONArray();
        series.add(EchartsUtil.seriesItem_Pie("注册人数", "55%", data));
        json.put("tooltip", EchartsUtil.tooltip_Pie());
        json.put("series", series);
        return json;
    }

    @Override
    public Float countRegTotali(Long agentId, Date date, Integer recLevel, Integer dateLength) {
        return baseDao.countRegTotali(agentId, date, recLevel, dateLength);
    }

    @Override
    @Transactional
    public void updateAllIncome() {
        String lockKey = RedisConstants.SYS_LOCK_KEY + "updateAllIncome";
        redisLock.lock(lockKey, 10);
        try {
            List<AgentPayUserEntity> payList = agentPayUserService.notGranTlist();
            for (AgentPayUserEntity pay : payList) {
                AgentUserEntity agentUserEntity = agentUserService.selectById(pay.getAgentId());
                if (agentUserEntity == null) {
                    agentPayUserService.updateIncomeGrant(pay.getId(), "2");
                    continue;
                }
                float currency = pay.getCurrency();
                int recLevel = pay.getRecLevel();
                Long[] ids = StringUtils.toChainIds(agentUserEntity.getChain());
                List<AgentIncomeEntity> agents = new ArrayList<>();
                for (Long id : ids) {
                    AgentUserEntity agent = agentUserService.selectById(id);
                    if (agent == null) {
                        continue;
                    } else {
                        agents.add(insertIncome(currency, agent.getId(), pay.getId(), pay.getRecLevel(), getScale(agent, recLevel)));
                    }
                }
                agents.add(insertIncome(currency, agentUserEntity.getId(), pay.getId(), pay.getRecLevel(), getScale(agentUserEntity, recLevel)));
                AgentIncomeEntity lastIncome = null;
                for (int i = 0; i < agents.size(); i++) {
                    AgentIncomeEntity income = agents.get(i);
                    if (lastIncome == null) {
                        income.setCurrency(currency * (income.getIncomeScale() / 100));
                    } else {
                        float tc = lastIncome.getCurrency();
                        income.setCurrency(tc * (income.getIncomeScale() / 100));
                        lastIncome.setCurrency(lastIncome.getCurrency() - income.getCurrency());
                    }
                    lastIncome = income;
                }
                for (AgentIncomeEntity agent : agents) {
                    baseDao.insert(agent);
                }
                agentPayUserService.updateIncomeGrant(pay.getId(), "1");
            }
        } finally {
            redisLock.unlock(lockKey);
        }
    }

    private AgentIncomeEntity insertIncome(float currency, long agentId, Long payRecordId, Integer recLevel, Float incomeScale) {
        AgentIncomeEntity entity = new AgentIncomeEntity();
        entity.setCurrency(currency);
        entity.setAgentId(agentId);
        entity.setPayRecordId(payRecordId);
        entity.setRecLevel(recLevel);
        entity.setIncomeScale(incomeScale);
        return entity;
    }

    /**
     * 获取代理商分成比例
     *
     * @param agent
     * @param recLevel
     * @return
     */
    private float getScale(AgentUserEntity agent, int recLevel) {
        if (recLevel == 1) {
            return agent.getDirectScale();
        } else {
            return agent.getIndirectScale();
        }
    }

}
